package com.example.concurrentprogramming8016.ReentrantReadWriteLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author liyanhao
 * @Date 2023-01-07 14:27
 */
public class ReentranReadWriteLockDemo {
    private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private Lock read = reentrantReadWriteLock.readLock();
    private Lock write = reentrantReadWriteLock.writeLock();

    //添加读锁
    public Data getData() {
        read.lock();
        try {
            System.out.println("readlock...");
            TimeUnit.SECONDS.sleep(2);
            System.out.print("休眠二秒");
            return new Data();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            read.unlock();
        }
    }

    public void setData() {
        write.lock();
        try {
            System.out.println("writelock...");
            System.out.print("休眠三秒");
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            write.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentranReadWriteLockDemo reentranReadWriteLockDemo = new ReentranReadWriteLockDemo();
        //测试并发进行读操作
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                reentranReadWriteLockDemo.getData();
            }, "thread-r-" + i).start();
        }
        //测试并发写锁操作
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println("写锁延迟一秒执行");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                reentranReadWriteLockDemo.setData();
            }, "thead-w-" + i).start();
        }
        for (; ; ) {
            TimeUnit.SECONDS.sleep(1);
            System.out.println("每过一秒打印一下...");
        }
    }

    class Data {

    }
}
